#include <GameEngine/UnitTest/unit_test.h>

#include <GameEngine/Core/Classes/rtti.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif


#ifndef DOXYGEN_IGNORE

//! Test class A
class _UnitTest_decl RTTI_A {
	GAMEENGINE_DECLARE_RTTI_SINGLE(RTTI_A)

public:
	RTTI_A() {}
	virtual ~RTTI_A() {}
};

//! Test class B (derives from test class A)
class _UnitTest_decl RTTI_B : public RTTI_A {
	GAMEENGINE_DECLARE_RTTI_PARENT(RTTI_B,RTTI_A)

public:
	RTTI_B() {}
	virtual ~RTTI_B() {}
};

//! Test class C
class _UnitTest_decl RTTI_C {
	GAMEENGINE_DECLARE_RTTI_SINGLE(RTTI_C)

public:
	RTTI_C() {}
	virtual ~RTTI_C() {}
};

//! Test class D
class _UnitTest_decl RTTI_D {

public:
	RTTI_D() {}
	virtual ~RTTI_D() {}
};

//! Test class E
class _UnitTest_decl RTTI_E : public RTTI_D {
	GAMEENGINE_DECLARE_RTTI_SINGLE(RTTI_E)

public:
	RTTI_E() {}
	virtual ~RTTI_E() {}
};

GAMEENGINE_IMPLEMENT_RTTI(RTTI_A)
GAMEENGINE_IMPLEMENT_RTTI(RTTI_B)
GAMEENGINE_IMPLEMENT_RTTI(RTTI_C)
GAMEENGINE_IMPLEMENT_RTTI(RTTI_E)

#endif


//! Launch the unit tests on RTTI support
/*!
 @return True if all unit tests on RTTI support were
         succesful, false otherwise
 */
bool UnitTest::test_core_rtti_functions() {
	bool res = true;

	// Get number of bytes
	MemoryManager::BytesCount bytes = MemoryManager::instance()->bytes();

	// Test Rtti on static class definition
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_A::is_a<RTTI_A>() == true ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_A::is_a<RTTI_B>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_A::is_a<RTTI_C>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_A::is_a<RTTI_D>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_A::is_a<RTTI_E>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_B::is_a<RTTI_A>() == true ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_B::is_a<RTTI_B>() == true ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_B::is_a<RTTI_C>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_B::is_a<RTTI_D>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_B::is_a<RTTI_E>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_C::is_a<RTTI_A>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_C::is_a<RTTI_B>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_C::is_a<RTTI_C>() == true ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_C::is_a<RTTI_D>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_C::is_a<RTTI_E>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_E::is_a<RTTI_A>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_E::is_a<RTTI_B>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_E::is_a<RTTI_C>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_E::is_a<RTTI_D>() == false ));
	res &= UNIT_TEST_ERROR( "[Rtti] Test is_a() (static class)", ( RTTI_E::is_a<RTTI_E>() == true ));

	// Get number of bytes
	res &= UNIT_TEST_ERROR( "[Rtti] Test memory leak", ( bytes == MemoryManager::instance()->bytes() ));

	// Return result
	return res;
}


#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif
